
-- $Id: Models.lua 72 2009-04-06 11:38:08Z Fylgjas $

-- ========================================================================= --
-- Copyright © 2009 Thomas ROBERT (aka Fylgjas EU - Marécage de Zangar)      --
-- ========================================================================= --
-- This file is part of FyLooter.                                            --
--                                                                           --
-- FyLooter is free software: you can redistribute it and/or modify it under --
-- the terms of the GNU General Public License as published by the Free      --
-- Software Foundation, either version 3 of the License, or (at your option) --
-- any later version.                                                        --
--                                                                           --
-- FyLooter is distributed in the hope that it will be useful, but WITHOUT   --
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     --
-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for  --
-- more details.                                                             --
--                                                                           --
-- You should have received a copy of the GNU General Public License along   --
-- with FyLooter. If not, see <http://www.gnu.org/licenses/>.                --
-- ========================================================================= --

local revision = tonumber(string.sub("$Rev: 72 $", 7, -3));

if (FyLooter.revision < revision) then
  FyLooter.revision = revision;
end

-- ========================================================================= --

-- 
-- MetaModel
--
local MetaModel = {};

-- 
-- MetaModel:GetPlayerIdx()
--
function MetaModel:GetPlayerIdx(playerName)
  for playerIdx, player in ipairs(FyLooter.db.players) do
    if (player.name == playerName) then
      return playerIdx;
    end
  end

  return nil;
end

-- 
-- MetaModel:GetCharacterIdx()
--
function MetaModel:GetCharacterIdx(characterName)
  for playerIdx, player in ipairs(FyLooter.db.players) do
    for characterIdx, character in ipairs(player.characters) do
      if (character == characterName) then
        return playerIdx, characterIdx;
      end
    end
  end

  return nil, nil;
end

-- 
-- MetaModel:GetCandidateIdx()
--
function MetaModel:GetCandidateIdx(candidateName)
  for candidateIdx, candidate in pairs(FyLooter.candidates) do
    if (candidate.name == candidateName) then
      return candidateIdx;
    end
  end

  return nil;
end

-- 
-- MetaModel:Update()
--
function MetaModel:Update()
  FyLooter.ScrollFrame:Update();
end

-- 
-- MetaModel:GetNumItems()
--
function MetaModel:GetNumItems()
  return #self.index;
end

-- 
-- MetaModel:GetData()
--
function MetaModel:GetData(i)
  return nil;
end

-- 
-- MetaModel:GetSelection()
--
function MetaModel:GetSelection()
  return self.selection;
end

-- 
-- MetaModel:SetSelection()
--
function MetaModel:SetSelection(i)
  if (self.selection == i) then
    self.selection = nil;
  else
    self.selection = i;
  end

  FyLooter.ScrollFrame:Update();
end

-- ========================================================================= --

-- 
-- FyLooter.CharactersModel
--
local charactersModel = { ["index"] = {} };
setmetatable(charactersModel, { __index = MetaModel });
FyLooter.CharactersModel = charactersModel;

-- 
-- FyLooter.CharactersModel:Update()
--
function charactersModel:Update()
  FyLooter:Delete(self.index);
  self.index = {};

  local players = FyLooter.db.players;

  for i = 1, #players do
    tinsert(self.index, { i, nil });

    if (players[i].isExpanded) then
      for j = 1, #players[i].characters do
        tinsert(self.index, { i, j });
      end
    end
  end

  MetaModel:Update();
end

-- 
-- FyLooter.CharactersModel:GetData()
--
function charactersModel:GetData(i)
  local playerIdx, characterIdx = unpack(self.index[i]);

  local player = FyLooter.db.players[playerIdx];
  
  local hasChild = false;
  if (#player.characters > 0) then
    hasChild = true;
  end

  if (not characterIdx) then
    return player.name, nil, 0, nil, nil, hasChild, player.isExpanded;
  else
    local character = player.characters[characterIdx];
    local class, color = UnitClass(character);

    return nil, character, UnitLevel(character), class, RAID_CLASS_COLORS[color], hasChild, nil, nil;
  end
end

-- 
-- FyLooter.CharactersModel:SetSelection()
--
function charactersModel:SetSelection(i)
  FyLooter.AdminFrame.RemoveButton:Disable();
  FyLooter.AdminFrame.UpButton:Disable();
  FyLooter.AdminFrame.DownButton:Disable();
  FyLooter.InsertFrame.PlayerEditBox:SetText("");

  MetaModel.SetSelection(self, i);
  i = self.selection;
  
  if (i) then
    FyLooter.AdminFrame.RemoveButton:Enable();

    local playerIdx, characterIdx = unpack(self.index[i]);

    FyLooter.InsertFrame.PlayerEditBox:SetText(FyLooter.db.players[playerIdx].name);
    
    if (not characterIdx) then
      if (i > 1) then FyLooter.AdminFrame.UpButton:Enable() end
      if (i < #self.index) then FyLooter.AdminFrame.DownButton:Enable() end
    end
  end
end

-- 
-- FyLooter.CharactersModel:Expand()
--
function charactersModel:Expand(i)
  local playerIdx = unpack(self.index[i]);

  FyLooter.db.players[playerIdx].isExpanded = true;

  self:Update();
end

-- 
-- FyLooter.CharactersModel:Collapse()
--
function charactersModel:Collapse(i)
  local playerIdx = unpack(self.index[i]);

  FyLooter.db.players[playerIdx].isExpanded = false;

  self:Update();
end

-- 
-- FyLooter.CharactersModel:Insert()
--
function charactersModel:Insert(playerName, characterName)
  local playerIdx = self:GetPlayerIdx(playerName);
  
  local players = FyLooter.db.players;

  if ((not characterName) or (characterName == "")) then
    if (not playerIdx) then
      tinsert(players, {
        ["name"] = playerName,
        ["isExpanded"] = true,
        ["characters"] = {},
      });

      FyLooter.pending = true;

      self:Update();
    else
      FyLooter:Debug("player with this name already exists");    -- TODO
    end
  else
    local characterIdx = self:GetCharacterIdx(characterName);

    if (not characterIdx) then
      if (playerIdx) then
        local player = players[playerIdx];

        tinsert(player.characters, characterName);

        table.sort(player.characters);
      else
        if ((not playerName) or (playerName == "")) then
          playerName = characterName;
        end
        tinsert(players, {
          ["name"] = playerName,
          ["isExpanded"] = true,
          ["characters"] = {
            characterName,
          },
        });
      end

      FyLooter.pending = true;

      self:Update();
    else
      FyLooter:Debug("character with this name already exists");    -- TODO
    end
  end
end

-- 
-- FyLooter.CharactersModel:Remove()
--
function charactersModel:Remove(i)
  local playerIdx, characterIdx = unpack(self.index[i]);

  local players = FyLooter.db.players;

  if (not characterIdx) then
    tremove(players, playerIdx);
  else
    tremove(players[playerIdx].characters, characterIdx);
  end

  FyLooter.pending = true;

  self:Update();
end

-- 
-- FyLooter.CharactersModel:Swap()
--
function charactersModel:Swap(i1, i2)
  if (i1 == i2) then return end

  local players = FyLooter.db.players;

  local tmp = players[i1];
  players[i1] = players[i2];
  players[i2] = tmp;

  FyLooter.pending = true;

  self:Update();
end

-- ========================================================================= --

-- 
-- FyLooter.CandidatesModel
--
local candidatesModel = { ["index"] = {} };
setmetatable(candidatesModel, { __index = MetaModel });
FyLooter.CandidatesModel = candidatesModel;

-- 
-- FyLooter.CandidatesModel:Update()
--
function candidatesModel:Update()
  FyLooter:Delete(self.index);
  self.index = {};

  local candidates = FyLooter.candidates;

  for id, candidate in pairs(candidates) do
    tinsert(self.index, id);
  end

  -- sort candidates according to their priority
  table.sort(self.index, function(i1, i2)
    local playerIdx1 = self:GetCharacterIdx(candidates[i1].name);
    local playerIdx2 = self:GetCharacterIdx(candidates[i2].name);

    return playerIdx1 < playerIdx2;
  end);

  MetaModel.Update(self);
end

-- 
-- FyLooter.CandidatesModel:GetData()
--
function candidatesModel:GetData(i)
  local candidate = FyLooter.candidates[self.index[i]];
  local name = candidate.name;
  local class, color = UnitClass(name);

  return nil, name, UnitLevel(name), class, RAID_CLASS_COLORS[color], false, nil, candidate.status;
end

-- 
-- FyLooter.CandidatesModel:SetSelection()
--
function candidatesModel:SetSelection(i)
  FyLooter.MasterFrame.PayButton:Disable();
  FyLooter.MasterFrame.FreeButton:Disable();

  MetaModel.SetSelection(self, i);
  i = self.selection;

  if (i) then
    FyLooter.MasterFrame.PayButton:Enable();
    FyLooter.MasterFrame.FreeButton:Enable();
  end
end

-- 
-- FyLooter.CandidatesModel:SetStatus()
--
function candidatesModel:SetStatus(candidateName, status)
  local candidateIdx = self:GetCandidateIdx(candidateName);

  FyLooter.candidates[candidateIdx].status = status;

  FyLooter.ScrollFrame:Update();
end

-- 
-- FyLooter.CandidatesModel:Kill()
--
function candidatesModel:Kill(i)
  local candidates = FyLooter.candidates;

  for k = i + 1, #self.index do
    local n1 = candidates[self.index[k - 1]].name;
    local n2 = candidates[self.index[k]].name;

    local i1 = self:GetCharacterIdx(n1);
    local i2 = self:GetCharacterIdx(n2);

    FyLooter:Debug("Kill() : swap("..i1.." "..n1..", "..i2.." "..n2..")");

    FyLooter.CharactersModel:Swap(i1, i2);

    self:Update();
  end
    
  FyLooter.pending = true;

  FyLooter:Commit();
end

-- ========================================================================= --

